package com.ifast.face.controller;


import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import javax.imageio.ImageIO;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.Base64Utils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import com.arcsoft.face.FaceInfo;
import com.ifast.common.base.AdminBaseController;
import com.ifast.common.utils.CheckUtil;
import com.ifast.face.domain.UserFaceInfo;
import com.ifast.face.dto.FaceSearchResDto;
import com.ifast.face.dto.FaceUserInfo;
import com.ifast.face.dto.ProcessInfo;
import com.ifast.face.enums.ErrorCodeEnum;
import com.ifast.face.service.FaceEngineService;
import com.ifast.face.service.UserFaceInfoService;
import com.ifast.face.util.ImageInfo;
import com.ifast.face.util.ImageUtil;
import com.ifast.face.util.Result;
import com.ifast.face.util.Results;
import com.ifast.face.util.WorkId;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;


@Controller
@RequestMapping("/face")
public class FaceController extends AdminBaseController {
 
    private String preHtml = "face/";
    
    @Autowired
    FaceEngineService faceEngineService;

    @Autowired
    UserFaceInfoService userFaceInfoService;

    @RequestMapping(value = "/index")
    public String demo() {
        return preHtml + "index";
    }


    @RequestMapping(value = "/faceAdd", method = RequestMethod.POST)
    @ResponseBody
    public Result<Object> faceAdd(@RequestParam("file") MultipartFile file, @RequestParam("groupId") Long groupId, @RequestParam("name") String name) {
        
       if (CheckUtil.isNull(file,groupId,name))
           return Results.newFailedResult("file is null");
         
       try (InputStream inputStream = file.getInputStream();){
           
            @SuppressWarnings("unused")
			ImageInfo imageInfo = ImageUtil.getRGBData(inputStream);

            //人脸特征获取
            byte[] bytes = null;// faceEngineService.extractFaceFeature(imageInfo);
            if (bytes == null) 
                return Results.newFailedResult(ErrorCodeEnum.NO_FACE_DETECTED);

            @SuppressWarnings("unused")
			String faceId = WorkId.sortUID(); 
            //人脸特征插入到数据库
            userFaceInfoService.save(UserFaceInfo.builder().name(name).groupId(groupId).faceFeature(bytes).faceId(faceId).build()); 
            //人脸信息添加到缓存
            faceEngineService.refresh(groupId);

            log.info("faceAdd:" + name);
            return Results.newSuccessResult();
        } catch (Exception e) {
        	e.printStackTrace();
        	return Results.newFailedResult(ErrorCodeEnum.UNKNOWN); 
        } 
    }

    @RequestMapping(value = "/faceSearch", method = RequestMethod.POST)
    @ResponseBody
    public Result<FaceSearchResDto> faceSearch(MultipartFile file, Long groupId) throws Exception {

        if (groupId == null) {
            return Results.newFailedResult("groupId is null");
        }

        InputStream inputStream = file.getInputStream();
        BufferedImage bufImage = ImageIO.read(inputStream);
        ImageInfo imageInfo = ImageUtil.bufferedImage2ImageInfo(bufImage);
        if (inputStream != null) {
            inputStream.close();
        } 
        //人脸特征获取
        List<ProcessInfo> process = faceEngineService.extractFaceFeature(imageInfo); 

        if (process == null) {
            return Results.newFailedResult(ErrorCodeEnum.NO_FACE_DETECTED);
        }
        ProcessInfo pInfo = process.get(0);
        //人脸比对，获取比对结果 
		List<FaceUserInfo> userFaceInfoList = faceEngineService.compareFaceFeature(pInfo.getFaceFeature(), groupId);


        if (CollectionUtil.isNotEmpty(userFaceInfoList)) {
            FaceUserInfo faceUserInfo = userFaceInfoList.get(0);
            FaceSearchResDto faceSearchResDto = new FaceSearchResDto();
            BeanUtil.copyProperties(faceUserInfo, faceSearchResDto);
            List<FaceInfo> faceInfoList = faceEngineService.detectFaces(imageInfo);
            int left = faceInfoList.get(0).getRect().getLeft();
            int top = faceInfoList.get(0).getRect().getTop();
            int width = faceInfoList.get(0).getRect().getRight() - left;
            int height = faceInfoList.get(0).getRect().getBottom()- top;

            Graphics2D graphics2D = bufImage.createGraphics();
            graphics2D.setColor(Color.RED);//红色
            BasicStroke stroke = new BasicStroke(5f);
            graphics2D.setStroke(stroke);
            graphics2D.drawRect(left, top, width, height);
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            ImageIO.write(bufImage, "jpg", outputStream);
            byte[] bytes1 = outputStream.toByteArray();
            faceSearchResDto.setImage("data:image/jpeg;base64," + Base64Utils.encodeToString(bytes1));
            faceSearchResDto.setAge(pInfo.getAge());
            faceSearchResDto.setGender(pInfo.getGender().equals(1) ? "女" : "男"); 
            return Results.newSuccessResult(faceSearchResDto);
        }


        return Results.newFailedResult(ErrorCodeEnum.FACE_DOES_NOT_MATCH);
    }


    @RequestMapping(value = "/detectFaces", method = RequestMethod.POST)
    @ResponseBody
    public List<FaceInfo> detectFaces(String image) throws IOException {
        byte[] bytes = Base64Utils.decodeFromString(image.trim());

        InputStream inputStream = new ByteArrayInputStream(bytes);
        ImageInfo imageInfo = ImageUtil.getRGBData(inputStream);

        if (inputStream != null) {
            inputStream.close();
        }
        List<FaceInfo> faceInfoList = faceEngineService.detectFaces(imageInfo);

        return faceInfoList;
    }

}
